import { Destroyable, react, reactJson, Event, track, HasOwner, reactJsonWithUndefined } from "earthsdk3";
import { MyProjectManager } from "../MyProjectManager";
import { Child, TransformedChild } from '@/scripts/dataTypes/interface'
import { ObjResettingWithEvent } from "earthsdk3";
import { ESRtsFeatureEditing } from "earthsdk3";
import { getsceneObjNumfromSceneTree } from "../utils";
import { ESGeoPolygon, FeatureColorJsonType } from "earthsdk3";
import { ElMessage } from "element-plus";
import { reqGetSelectQuery } from "@/api";
import { ESRtsPolygon } from "../esobjs/ESRtsPolygon";
import { ESRtsEexturedPolygon } from "../esobjs/ESRtsEexturedPolygon";

class SelectResettting extends Destroyable {
    constructor(featureSelect: FeatureSelect, owner: MyProjectManager) {
        super();
        const sceneObject = owner.createSceneObject(ESGeoPolygon) as ESGeoPolygon
        sceneObject.stroked = true
        sceneObject.filled = false
        sceneObject.strokeWidth = 2
        sceneObject.editing = true

        {
            const updata = () => {
                if (sceneObject.editing) return;
                if (!sceneObject.points) return;
                featureSelect.points = [...sceneObject.points, sceneObject.points[0]]

            }
            this.dispose(sceneObject.editingChanged.don(updata))
        }

        this.dispose(() => {
            featureSelect.clear()
            sceneObject.editing = false
            sceneObject && owner.destroySceneObject(sceneObject);
        })
    }
}


function isNumber(value: any): boolean {
    return typeof value === 'number' && !isNaN(value);
}

export class FeatureSelect extends HasOwner<MyProjectManager> {

    get es3DTileset() { return this.owner.cimrtsManager.eSRtsTileset.es3DTileset }

    // 框选事件
    private _selectEvent = this.dv(new Event<[string]>());
    get selectEvent() { return this._selectEvent; }

    // 拾取处理
    private _selectResettting = this.dv(new ObjResettingWithEvent(this.selectEvent, (res) => {
        if (!res || res != "select") {
            return undefined;
        }
        return new SelectResettting(this, this.owner);
    }))
    get selectResettting() { return this._selectResettting; }

    // 多边形的点位
    private _points = this.dv(reactJson<any>([]));
    get points() { return this._points.value; }
    get pointsChanged() { return this._points.changed; }
    set points(value: any) { this._points.value = value; }

    // 多边形的点位
    private _selectIds = this.dv(reactJson<any>([]));
    get selectIds() { return this._selectIds.value; }
    get selectIdsChanged() { return this._selectIds.changed; }
    set selectIds(value: any) { this._selectIds.value = value; }

    // 框选查询信息
    private _selectQueryInfo = this.dv(reactJson<any>([]));
    get selectQueryInfo() { return this._selectQueryInfo.value; }
    get selectQueryInfoChanged() { return this._selectQueryInfo.changed; }
    set selectQueryInfo(value: any) { this._selectQueryInfo.value = value; }

    // 框选查询信息分页
    private _selectQueryInfoPages = this.dv(reactJson<any>([]));
    get selectQueryInfoPages() { return this._selectQueryInfoPages.value; }
    get selectQueryInfoPagesChanged() { return this._selectQueryInfoPages.changed; }
    set selectQueryInfoPages(value: any) { this._selectQueryInfoPages.value = value; }

    // 分页信息
    private _pages = this.dv(reactJson<any>({
        pageNum: 1,
        pageSize: 5,
        total: 0
    }));
    get pages() { return this._pages.value; }
    get pagesChanged() { return this._pages.changed; }
    set pages(value: any) { this._pages.value = value; }

    // 框选查询分页
    selectQueryPageChange() {
        if (!this.selectQueryInfo.length) return;
        this.selectQueryInfoPages = this._selectQueryInfo.value.slice((this.pages.pageNum - 1) * this.pages.pageSize, this.pages.pageNum * this.pages.pageSize)
    }

    // 设置框选json字符串
    setSelectJsonStr() {
        const points = this.points.map((p: [number, number, number]) => [p[0], p[1]])
        const json = {
            "type": "Polygon",
            "coordinates": [
                [
                    ...points
                ]
            ]
        }
        return JSON.stringify(json)
    }

    // 框选查询
    async getSelectQuery() {
        // 设置框选json字符串
        const str = this.setSelectJsonStr();
        try {
            const param = {
                "tileServiceName": this._tileServiceName,
                "json": str
            }
            const res = await reqGetSelectQuery(param)
            console.log("框选查询", res);

            // @ts-ignore
            if (res.status !== 'ok') return
            this._selectQueryInfo.value = res.data
            this.selectQueryInfoPages = res.data.slice((this.pages.pageNum - 1) * this.pages.pageSize, this.pages.pageNum * this.pages.pageSize)
            this.pages = {
                ...this.pages,
                total: res.data.length
            }
        } catch (error) {
            console.error(error)
        }
    }

    // 飞行到点击的要素
    flyToFeature(id: string) {
        const { boundingbox, lonLatboundingbox } = this.selectQueryInfoPages.find((e: any) => e.id == id)
        const radius = boundingbox.sphereRadius * 3 + boundingbox.maxZ
        const rectangle: [number, number, number, number] = [lonLatboundingbox.minX, lonLatboundingbox.minY, lonLatboundingbox.maxX, lonLatboundingbox.maxY]
        this.owner.activeViewer?.flyToBoundingSphere(rectangle, radius)
    }

    // 框选高亮
    highlight(ids: string[]) {
        const json: any = ids.map((e: any) => {
            return {
                value: e,
                rgba: [1, 0, 0, 1]
            }
        })
        this.es3DTileset.setFeatureColor("id", json)
    }

    // 根据id数组创建 要素
    async createFeatureByIds(ids: string[]) {

        const filterIds = ids.filter((id: any) => !this.owner.cimrtsSceneTreeWrapper?.getTreeItemFromSceneObjId(id))
        if (!filterIds.length) {
            ElMessage.warning("没有要创建的要素")
            return;
        }

        // 1.创建一个文件夹
        const group = this.owner.cimrtsSceneTreeWrapper?.createGroupTreeItem() as any
        const json = this.owner.cimrtsSceneTreeWrapper?.json.root.children as any
        const name = "框选要素"
        const num = this.owner.setGroupName(json, name)
        group.name = `${name}(${num})`

        const eSRtsTileset = this.owner.cimrtsManager.eSRtsTileset

        filterIds.map(async (id: any, i: any) => {
            const property = await eSRtsTileset.getFeatureProperty(id) as any;
            const param = property.geometry.param

            let sceneObject: ESRtsFeatureEditing | ESRtsPolygon | ESRtsEexturedPolygon | undefined = undefined

            // 绘制对象 
            if (param) {
                const esobjJson = JSON.parse(param)
                sceneObject = this.owner.createSceneObjectFromJson(esobjJson) as ESRtsFeatureEditing | ESRtsPolygon
                //隐藏原来大的中的feature
                eSRtsTileset.setFeatureVisable('id', [{ value: id, visable: false }]);
                sceneObject.d(() => { eSRtsTileset.setFeatureVisable('id', [{ value: id, visable: true }]) });

                sceneObject.uiShowprops = property.allFields.map((e: any) => {
                    return {
                        featureClassName: e.featureClassName,
                        fields: e.fields.map((f: any) => {
                            return {
                                key: f.name,
                                type: f.type,
                                value: f.type != "Double" ? f.value : (isNumber(f.value) ? Number(f.value.toFixed(3)) : "")
                            }
                        })
                    }
                })
                sceneObject.datasetName = property.datasetName
                sceneObject.featureId = id
                // @ts-ignore
                sceneObject.geometryId = property.geometry.id
                // @ts-ignore
                sceneObject.create = false

            } else {
                sceneObject = this.owner.createSceneObject(ESRtsFeatureEditing, id) as ESRtsFeatureEditing
                sceneObject.offset = [0, 0, 0]

                // @ts-ignore
                await sceneObject.init(this.owner.cimrtsManager.eSRtsTileset, id)
                const name = this.selectQueryInfo.find((e: any) => e.id === id)?.name
                const newName = "框选要素_" + (name ? name : (sceneObject.id ? sceneObject.id : ""))
                const num = getsceneObjNumfromSceneTree(sceneObject.typeName, this.owner.cimrtsSceneTreeWrapper)
                sceneObject.name = `${newName}(${num})`
            }

            const treeItem = this.owner.createdTreeItemInnerGroup(this.owner.cimrtsSceneTreeWrapper, group)
            treeItem.sceneObject = sceneObject;

        })

    }

    // 清除参数
    clear() {
        this.selectQueryInfoPages = []
        this.points = [];
        this.pages = {
            pageNum: 1,
            pageSize: 5,
            total: 0
        }

        if (this.selectQueryInfo.length) {
            const json = this.selectQueryInfo.map((e: any) => {
                return {
                    value: e.id,
                    rgba: [1, 1, 1, 1]
                }
            }) as FeatureColorJsonType[]
            this.es3DTileset.setFeatureColor("id", json)
            this.selectQueryInfo = []
        }
    }

    constructor(private _tileServiceName: string, owner: MyProjectManager) {
        super(owner);

        {
            const updata = async () => {
                if (!this.points.length || this.points.length < 3) return;
                // 框选查询
                await this.getSelectQuery()
                // 框选高亮
                const ids = this.selectQueryInfo.map((e: any) => e.id)
                this.highlight(ids)

            }
            this.dispose(this.pointsChanged.don(updata))
        }

        {
            const updata = async (newVal: any, oldVal: any) => {
                if (!this.points.length) return;
                // 把上次选中的要素恢复
                if (oldVal.length && (newVal.length != this.selectQueryInfo.length)) {

                    const json = oldVal.map((e: any) => {
                        return {
                            value: e,
                            rgba: [1, 0, 0, 1]
                        }
                    }) as FeatureColorJsonType[]
                    this.es3DTileset.setFeatureColor("id", json)
                }
                const json = newVal.map((e: any) => {
                    return {
                        value: e,
                        rgba: [0, 1, 0, 1]
                    }
                }) as FeatureColorJsonType[]
                this.es3DTileset.setFeatureColor("id", json)
            }
            this.dispose(this.selectIdsChanged.don(updata))
        }

    }
}